This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.


source("JULES-ES-1p0-common-packages.R")
source("JULES-ES-1p0-common-functions.R")


makeTimeseriesEnsembleSSP <- function(ensloc, variable, nstart, nend, cn = 1850:2100){
  
  ysec <- 31536000
  
  nens <- (nend - nstart) + 1
  # nens is number of ensemble members
  # nts length of timeseries
  # cn is colnames()
  datmat <- matrix(NA, nrow = nens, ncol = length(cn))
  colnames(datmat) <- cn
  
  enslist <- paste("P", formatC(nstart:nend, width=4, flag="0"), sep="")
  
  for(i in 1:nens){
    
    ensmember <- enslist[i]
    
    fn <- paste0(ensloc,'JULES-ES-1p0_',ensmember,'_Annual_global.nc')
    
    try(nc <- nc_open(paste0(fn)))
    #try(localtime <- ncvar_get(nc, 'time'))
    
    # This part compensates for the fact that sometimes years are missing
    #try(localyear <- floor(2100 + (localtime / ysec)))
    #try(ix <- which(cn%in%localyear))
    
    try(dat <- extractTimeseries(nc, variable))
    
    try(datmat[i, ] <- dat)
    nc_close(nc)
  }
  datmat
}

getStandardMemberSSP <- function(ensloc, variable, nts = 251, cn = 1850:2100){
  
  datmat <- matrix(NA, nrow = 1, ncol = nts)
  colnames(datmat) <- cn
  
  ensmember <- 'S3'
  #fn <- paste0(ensloc,ensmember,'/stats/','JULES-ES-1p0_',ensmember,'_Annual_global.nc')
  fn <- paste0(ensloc,'JULES-ES-1p0_',ensmember,'_Annual_global.nc')
  
  try(nc <- nc_open(paste0(fn)))
  try(dat <- extractTimeseries(nc, variable))
  
  datmat[1, ] <- dat
  nc_close(nc)
  datmat
  
}


ensloc_ssp585_S3 <- '/data/users/hadaw/JULES_ES_PPE/u-cf932/'
ensloc_ssp585_RAD <- '/data/users/hadaw/JULES_ES_PPE/u-ck647/'

ysec = 60*60*24*365
sspyears <- 1850:2100

if (file.exists("ensemble_timeseries_ssp_2022-08-09.rdata")) {
  load("ensemble_timeseries_ssp_2022-08-09.rdata")
} else {
  
  # primary carbon cycle outputs
  npp_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "npp_nlim_lnd_sum", cn = sspyears) / (1e12/ysec)
  
  nbp_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "nbp_lnd_sum", cn = sspyears) / (1e12/ysec)
  
  cSoil_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "cSoil_lnd_sum", cn = sspyears) / 1e12
  
  cVeg_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "cVeg_lnd_sum", cn = sspyears) / 1e12
  
  lai_lnd_mean_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "lai_lnd_mean", cn = sspyears)
  
  # fluxes
  rh_lnd_sum_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "rh_lnd_sum", cn = sspyears) / (1e12/ysec)
  
  fLuc_lnd_sum_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "fLuc_lnd_sum", cn = sspyears) / (1e12/ysec)
 
  fHarvest_lnd_sum_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "fHarvest_lnd_sum", cn = sspyears) / (1e12/ysec)
  
  # fractions
  treeFrac_lnd_mean_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "treeFrac_lnd_mean", cn = sspyears)

  shrubFrac_lnd_mean_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "shrubFrac_lnd_mean", cn = sspyears)  
  
  baresoilFrac_lnd_mean_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "baresoilFrac_lnd_mean", cn = sspyears)  
  
  c3PftFrac_lnd_mean_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "c3PftFrac_lnd_mean", cn = sspyears) 
  
  c4PftFrac_lnd_mean_ens_ssp585_S3 <- makeTimeseriesEnsembleSSP(ensloc = ensloc_ssp585_S3,
                                                 nstart = 499, nend = 999, variable = "c4PftFrac_lnd_mean", cn = sspyears)   
  
  save(npp_ens_ssp585_S3, nbp_ens_ssp585_S3, cSoil_ens_ssp585_S3, cVeg_ens_ssp585_S3, lai_lnd_mean_ens_ssp585_S3, rh_lnd_sum_ens_ssp585_S3, fLuc_lnd_sum_ens_ssp585_S3, fHarvest_lnd_sum_ens_ssp585_S3,
       treeFrac_lnd_mean_ens_ssp585_S3, shrubFrac_lnd_mean_ens_ssp585_S3, baresoilFrac_lnd_mean_ens_ssp585_S3,c3PftFrac_lnd_mean_ens_ssp585_S3, c4PftFrac_lnd_mean_ens_ssp585_S3,
       file = "ensemble_timeseries_ssp_2022-08-09.rdata" )
  
}
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: npp_nlim_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0855_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: cSoil_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0852_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: cSoil_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0853_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: cVeg_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0842_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: cVeg_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0850_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: cVeg_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0851_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: lai_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0828_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: lai_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0834_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: lai_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0837_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: lai_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0838_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: lai_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0921_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: rh_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0825_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: rh_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0827_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: rh_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0832_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: rh_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0921_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fLuc_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0854_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fLuc_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0856_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fLuc_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0857_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fLuc_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0858_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fLuc_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0859_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fLuc_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0860_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fHarvest_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0840_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fHarvest_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0841_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: fHarvest_lnd_sum"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0921_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: treeFrac_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0921_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: shrubFrac_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0921_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: baresoilFrac_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0921_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: c3PftFrac_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0921_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
[1] "vobjtovarid4: error #F: I could not find the requsted var (or dimvar) in the file!"
[1] "var (or dimvar) name: c4PftFrac_lnd_mean"
[1] "file name: /data/users/hadaw/JULES_ES_PPE/u-cf932/JULES-ES-1p0_P0921_Annual_global.nc"
Error in vobjtovarid4(nc, varid, verbose = verbose, allowdimvar = TRUE) : 
  Variable not found
## ----------------------------------------------------------------------
## Anomalize ensemble
## ----------------------------------------------------------------------

npp_ens_anom_ssp585_S3 <- anomalizeTSmatrix(npp_ens_ssp585_S3, 1:20)
nbp_ens_anom_ssp585_S3 <- anomalizeTSmatrix(nbp_ens_ssp585_S3, 1:20)
cSoil_ens_anom_ssp585_S3 <- anomalizeTSmatrix(cSoil_ens_ssp585_S3, 1:20)
cVeg_ens_anom_ssp585_S3 <- anomalizeTSmatrix(cVeg_ens_ssp585_S3, 1:20)

rh_lnd_sum_ens_anom_ssp585_S3 <- anomalizeTSmatrix(rh_lnd_sum_ens_ssp585_S3, 1:20)
fLuc_lnd_sum_ens_anom_ssp585_S3 <- anomalizeTSmatrix(fLuc_lnd_sum_ens_ssp585_S3, 1:20)
lai_lnd_mean_ens_anom_ssp585_S3 <- anomalizeTSmatrix(lai_lnd_mean_ens_ssp585_S3, 1:20) 

fHarvest_lnd_sum_ens_anom_ssp585_S3 <- anomalizeTSmatrix(fHarvest_lnd_sum_ens_ssp585_S3, 1:20)
treeFrac_lnd_mean_ens_anom_ssp585_S3 <- anomalizeTSmatrix(treeFrac_lnd_mean_ens_ssp585_S3, 1:20)
shrubFrac_lnd_mean_ens_anom_ssp585_S3 <- anomalizeTSmatrix(shrubFrac_lnd_mean_ens_ssp585_S3, 1:20)
baresoilFrac_lnd_mean_ens_anom_ssp585_S3 <- anomalizeTSmatrix(baresoilFrac_lnd_mean_ens_ssp585_S3, 1:20)
c3PftFrac_lnd_mean_ens_anom_ssp585_S3 <- anomalizeTSmatrix(c3PftFrac_lnd_mean_ens_ssp585_S3, 1:20)
c4PftFrac_lnd_mean_ens_anom_ssp585_S3 <- anomalizeTSmatrix(c4PftFrac_lnd_mean_ens_ssp585_S3, 1:20)

#total_land_carbon_anom <- anomalizeTSmatrix(total_land_carbon_ens, 1:20)

transpval <- 30
linecol = 'black'

par(mfrow= c(3,5), las = 1, mar = c(4,4,1,1))

matplot(sspyears, t(npp_ens_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'NPP', xlab = '', ylab = 'GtC')

matplot(sspyears,t(nbp_ens_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'NBP', xlab = '', ylab = 'GtC')

matplot(sspyears,t(cSoil_ens_ssp585_S3), 
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'cSoil', xlab = '', ylab = 'GtC')
 
matplot(sspyears,t(cVeg_ens_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval), 
        main = 'cVeg', xlab = '', ylab = 'GtC' )

matplot(sspyears,t(rh_lnd_sum_ens_ssp585_S3 ),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'RH', xlab = '', ylab = 'GtC')

matplot(sspyears,t(fLuc_lnd_sum_ens_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'fLuc', xlab = '', ylab = 'GtC')

matplot(sspyears,t(lai_lnd_mean_ens_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'LAI', xlab = '', ylab = 'GtC')

matplot(sspyears,t(fHarvest_lnd_sum_ens_ssp585_S3), 
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'fHarvest', xlab = '', ylab = 'GtC')

matplot(sspyears,t(treeFrac_lnd_mean_ens_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'treeFrac', xlab = '', ylab = '%')

matplot(sspyears,t(shrubFrac_lnd_mean_ens_ssp585_S3), 
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'shrubFrac', xlab = '', ylab = '%')

matplot(sspyears,t(baresoilFrac_lnd_mean_ens_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'baresoilFrac', xlab = '', ylab = '%')

matplot(sspyears,t(c3PftFrac_lnd_mean_ens_ssp585_S3), type = 'l', 
        lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'c3PftFrac', xlab = '', ylab = '%')

matplot(sspyears,t(c4PftFrac_lnd_mean_ens_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'c4PftFrac', xlab = '',ylab = '%')

NA
NA

transpval <- 30
linecol = 'black'

par(mfrow= c(3,5), las = 1, mar = c(4,4,1,1))

matplot(sspyears, t(npp_ens_anom_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'NPP', xlab = '', ylab = 'GtC')

matplot(sspyears,t(nbp_ens_anom_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'NBP', xlab = '', ylab = 'GtC')

matplot(sspyears,t(cSoil_ens_anom_ssp585_S3), 
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'cSoil', xlab = '', ylab = 'GtC')
 
matplot(sspyears,t(cVeg_ens_anom_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval), 
        main = 'cVeg', xlab = '', ylab = 'GtC' )

matplot(sspyears,t(rh_lnd_sum_ens_anom_ssp585_S3 ),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'RH', xlab = '', ylab = 'GtC')

matplot(sspyears,t(fLuc_lnd_sum_ens_anom_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'fLuc', xlab = '', ylab = 'GtC')

matplot(sspyears,t(lai_lnd_mean_ens_anom_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'LAI', xlab = '', ylab = 'GtC')

matplot(sspyears,t(fHarvest_lnd_sum_ens_anom_ssp585_S3), 
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'fHarvest', xlab = '', ylab = 'GtC')

matplot(sspyears,t(treeFrac_lnd_mean_ens_anom_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'treeFrac', xlab = '', ylab = '%')

matplot(sspyears,t(shrubFrac_lnd_mean_ens_anom_ssp585_S3), 
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'shrubFrac', xlab = '', ylab = '%')

matplot(sspyears,t(baresoilFrac_lnd_mean_ens_anom_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'baresoilFrac', xlab = '', ylab = '%')

matplot(sspyears,t(c3PftFrac_lnd_mean_ens_anom_ssp585_S3), type = 'l', 
        lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'c3PftFrac', xlab = '', ylab = '%')

matplot(sspyears,t(c4PftFrac_lnd_mean_ens_anom_ssp585_S3),
        type = 'l', lty = 'solid', col = makeTransparent(linecol, transpval),
        main = 'c4PftFrac', xlab = '',ylab = '%')

NA
NA

0.1 Which ensemble members match constraints?

Start with Level 2 (Andy’s constraints in NPP, NBP, cSoil and cVeg)


ix_mv <- which(sspyears %in% 1996:2015)

yvec_constraints <- c('npp_ens_ssp585_S3', 'nbp_ens_ssp585_S3', 'cSoil_ens_ssp585_S3', 'cVeg_ens_ssp585_S3')

# Matrix of constraint output modern values (1996 - 2015)
Y_const_ssp585_mv <- matrix(data = NA, nrow = nrow(npp_ens_ssp585_S3), ncol = length(yvec_constraints_vec ))
colnames(Y_const_ssp585_mv) <- yvec_constraints

for(i in 1:length(yvec_constraints)){
  
  Y_trunc <- get(yvec_constraints[i])[, ix_mv]
  Y_trunc_mean <- apply(Y_trunc, 1, mean, na.rm = TRUE)
  Y_const_ssp585_mv[,i] <- Y_trunc_mean
}

createConstraintString <- function(yvec, mins, maxes){
  # This function constructs a logical expression as a string to be evaluated
  out <- 'which('
  
  for(i in 1:length(yvec)){
    
    if(i<length(yvec)){
      
    subconst <- paste0('Y_unif','[,', '"',yvec[i],'"',']', '>', mins[i], '&', 'Y_unif','[,', '"',yvec[i], '"',']' , '<', maxes[i], '&')
    }
    
    else{
     subconst <-  paste0('Y_unif','[,', '"',yvec[i],'"',']', '>', mins[i], '&', 'Y_unif','[,', '"',yvec[i], '"',']' , '<', maxes[i])
    }
   out <-  paste0(out, subconst)
  }
  
  out <- paste0(out, ')')
}


AW_mins <- c(35, 0, 750, 300)
AW_maxes <- c(80, 10000, 3000, 800)

Y_unif <- Y_const_ssp585_mv
ix_kept <- eval(parse(text = createConstraintString(yvec=yvec_constraints, mins = AW_mins, maxes = AW_maxes)))



#eval(parse(text = paste0()))

inputConstraintSize <- function(Y_unif, yvec, mins, maxes){
  # Calculate the indices of Y_unif that are within the bounds set by mins and maxes
  
  
  ix_kept <- eval(parse(text = createConstraintString(yvec=yvec, mins = mins, maxes = maxes)))
  
  prop_kept <- length(ix_kept) / nrow(Y_unif)
  
  return(list(ix_kept = ix_kept, prop_kept = prop_kept))
  
}
  

0.1.1 Timeseries of absolute vales


lcol_wave01 <- makeTransparent('firebrick',  80)
lcol_wave01_level2 <- makeTransparent('gold',  80)
stancol = 'black'

linePlotMultiEns <- function(years, ens1, ens2, col1, col2, ylab, main, ylim = NULL){
  # Plot wave00 and wave01 timeseries on top of one another
  
  nt <- length(years) 
  if(is.null(ylim)){
    
  #ylim = range(c(ens1[,1], ens1[,nt], ens2[,1], ens2[ ,nt]))
  ylim = range(c(ens1,ens2))
  }
  
  else ylim <- ylim
  
  matplot(years, t(ens1), type = 'l', lty = 'solid',ylim = ylim, col = col1,
        ylab = ylab, main = main, xlab = '',
        bty = 'n', lwd = 1.5)
  matlines(years, t(ens2), col = col2, lty = 'solid', lwd = 1.5)
}


par(mfrow= c(3,5), las = 1, mar = c(4,4,1,0))

linePlotMultiEns(years = sspyears, ens1 = npp_ens_ssp585_S3,
                 ens2 = npp_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'NPP')

linePlotMultiEns(years = sspyears, ens1 = nbp_ens_ssp585_S3,
                 ens2 = nbp_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'NBP')

linePlotMultiEns(years = sspyears, ens1 = cSoil_ens_ssp585_S3,
                 ens2 = cSoil_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'cSoil')

linePlotMultiEns(years = sspyears, ens1 = cVeg_ens_ssp585_S3,
                 ens2 = cVeg_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'cVeg')


linePlotMultiEns(years = sspyears, ens1 = rh_lnd_sum_ens_ssp585_S3,
                 ens2 = rh_lnd_sum_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'RH')

linePlotMultiEns(years = sspyears, ens1 = fLuc_lnd_sum_ens_ssp585_S3,
                 ens2 = fLuc_lnd_sum_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'fLuc')


linePlotMultiEns(years = sspyears, ens1 = lai_lnd_mean_ens_ssp585_S3,
                 ens2 = lai_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'LAI')

linePlotMultiEns(years = sspyears, ens1 = fHarvest_lnd_sum_ens_ssp585_S3,
                 ens2 = fHarvest_lnd_sum_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'fHarvest')


linePlotMultiEns(years = sspyears, ens1 = treeFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = treeFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'treeFrac')

linePlotMultiEns(years = sspyears, ens1 = shrubFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = shrubFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'shrubFrac')

linePlotMultiEns(years = sspyears, ens1 = baresoilFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = baresoilFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'baresoilFrac')


linePlotMultiEns(years = sspyears, ens1 = c3PftFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = c3PftFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'c3PftFrac')

linePlotMultiEns(years = sspyears, ens1 = c4PftFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = c4PftFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'c4PftFrac')
reset()

legend('bottomright', legend = c('wave01', 'wave01 level2'), lty = 'solid', lwd = 1.5, col = c(lcol_wave01, lcol_wave01_level2), inset = c(0.05, 0.15) )

0.1.2 Anomaly timeseries


par(mfrow= c(3,5), las = 1, mar = c(4,4,1,0))

linePlotMultiEns(years = sspyears, ens1 = npp_ens_anom_ssp585_S3,
                 ens2 = npp_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'NPP')

linePlotMultiEns(years = sspyears, ens1 = nbp_ens_anom_ssp585_S3,
                 ens2 = nbp_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'NBP')

linePlotMultiEns(years = sspyears, ens1 = cSoil_ens_anom_ssp585_S3,
                 ens2 = cSoil_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'cSoil')

linePlotMultiEns(years = sspyears, ens1 = cVeg_ens_anom_ssp585_S3,
                 ens2 = cVeg_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'cVeg')


linePlotMultiEns(years = sspyears, ens1 = rh_lnd_sum_ens_anom_ssp585_S3,
                 ens2 = rh_lnd_sum_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'RH')

linePlotMultiEns(years = sspyears, ens1 = fLuc_lnd_sum_ens_anom_ssp585_S3,
                 ens2 = fLuc_lnd_sum_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'fLuc')


linePlotMultiEns(years = sspyears, ens1 = lai_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = lai_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'LAI')

linePlotMultiEns(years = sspyears, ens1 = fHarvest_lnd_sum_ens_anom_ssp585_S3,
                 ens2 = fHarvest_lnd_sum_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'fHarvest')


linePlotMultiEns(years = sspyears, ens1 = treeFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = treeFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'treeFrac')

linePlotMultiEns(years = sspyears, ens1 = shrubFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = shrubFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'shrubFrac')

linePlotMultiEns(years = sspyears, ens1 = baresoilFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = baresoilFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'baresoilFrac')


linePlotMultiEns(years = sspyears, ens1 = c3PftFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = c3PftFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'c3PftFrac')

linePlotMultiEns(years = sspyears, ens1 = c4PftFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = c4PftFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'c4PftFrac')
reset()

legend('bottomright', legend = c('wave01', 'wave01 level2'), lty = 'solid', lwd = 2, col = c(lcol_wave01, lcol_wave01_level2), inset = c(0.05, 0.15) )

NA
NA

0.2 Include Tree fraction data


load('treefrac/global_frac_cci.RData')

frac_cci <- c(global_frac_cci[1] + global_frac_cci[2], global_frac_cci[3], global_frac_cci[4], global_frac_cci[5], global_frac_cci[8] )
#frac_mv <- c(standard_modern_value['treeFrac_lnd_mean'], standard_modern_value['c3PftFrac_lnd_mean'], #standard_modern_value['c4PftFrac_lnd_mean'], standard_modern_value['shrubFrac_lnd_mean'], standard_modern_value['baresoilFrac_lnd_mean']  )


fraclab = c('Trees', 'C3 grasses', 'C4 grasses', 'Shrubs', 'Bare soil')


# Half and double the LC CCI data to get bounds for constraining JULES ES-1.0
frac_cci_max <- frac_cci + (0.5*frac_cci)
frac_cci_min <- frac_cci - (0.5*frac_cci)

ix_mv <- which(sspyears %in% 1996:2015)

yvec_constraints <- c('npp_ens_ssp585_S3', 'nbp_ens_ssp585_S3', 'cSoil_ens_ssp585_S3', 'cVeg_ens_ssp585_S3','baresoilFrac_lnd_mean_ens_ssp585_S3')

# Matrix of constraint output modern values (1996 - 2015)
Y_const_ssp585_mv <- matrix(data = NA, nrow = nrow(npp_ens_ssp585_S3), ncol = length(yvec_constraints))
colnames(Y_const_ssp585_mv) <- yvec_constraints

for(i in 1:length(yvec_constraints)){
  
  Y_trunc <- get(yvec_constraints[i])[, ix_mv]
  Y_trunc_mean <- apply(Y_trunc, 1, mean, na.rm = TRUE)
  Y_const_ssp585_mv[,i] <- Y_trunc_mean
}
const_mins <- c(35, 0, 750, 300, frac_cci_min['bare soil']*100)
const_maxes <- c(80, 10000, 3000, 800, frac_cci_max['bare soil']*100)

Y_unif <- Y_const_ssp585_mv
ix_kept <- eval(parse(text = createConstraintString(yvec=yvec_constraints, mins = const_mins, maxes = const_maxes)))

lcol_wave01 <- makeTransparent('firebrick',  120)
lcol_wave01_level2 <- makeTransparent('gold',  120)
stancol = 'black'

linePlotMultiEns <- function(years, ens1, ens2, col1, col2, ylab, main, ylim = NULL){
  # Plot wave00 and wave01 timeseries on top of one another
  
  nt <- length(years) 
  if(is.null(ylim)){
    
  #ylim = range(c(ens1[,1], ens1[,nt], ens2[,1], ens2[ ,nt]))
  ylim = range(c(ens1,ens2))
  }
  
  else ylim <- ylim
  
  matplot(years, t(ens1), type = 'l', lty = 'solid',ylim = ylim, col = col1,
        ylab = ylab, main = main, xlab = '',
        bty = 'n', lwd = 1.5)
  matlines(years, t(ens2), col = col2, lty = 'solid', lwd = 1.5)
}


par(mfrow= c(3,5), las = 1, mar = c(4,4,1,0))

linePlotMultiEns(years = sspyears, ens1 = npp_ens_ssp585_S3,
                 ens2 = npp_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'NPP')

linePlotMultiEns(years = sspyears, ens1 = nbp_ens_ssp585_S3,
                 ens2 = nbp_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'NBP')

linePlotMultiEns(years = sspyears, ens1 = cSoil_ens_ssp585_S3,
                 ens2 = cSoil_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'cSoil')

linePlotMultiEns(years = sspyears, ens1 = cVeg_ens_ssp585_S3,
                 ens2 = cVeg_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'cVeg')


linePlotMultiEns(years = sspyears, ens1 = rh_lnd_sum_ens_ssp585_S3,
                 ens2 = rh_lnd_sum_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'RH')

linePlotMultiEns(years = sspyears, ens1 = fLuc_lnd_sum_ens_ssp585_S3,
                 ens2 = fLuc_lnd_sum_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'fLuc')


linePlotMultiEns(years = sspyears, ens1 = lai_lnd_mean_ens_ssp585_S3,
                 ens2 = lai_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'LAI')

linePlotMultiEns(years = sspyears, ens1 = fHarvest_lnd_sum_ens_ssp585_S3,
                 ens2 = fHarvest_lnd_sum_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'fHarvest')


linePlotMultiEns(years = sspyears, ens1 = treeFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = treeFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'treeFrac')

linePlotMultiEns(years = sspyears, ens1 = shrubFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = shrubFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'shrubFrac')

linePlotMultiEns(years = sspyears, ens1 = baresoilFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = baresoilFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'baresoilFrac')


linePlotMultiEns(years = sspyears, ens1 = c3PftFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = c3PftFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'c3PftFrac')

linePlotMultiEns(years = sspyears, ens1 = c4PftFrac_lnd_mean_ens_ssp585_S3,
                 ens2 = c4PftFrac_lnd_mean_ens_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'c4PftFrac')
reset()

legend('bottomright', legend = c('wave01', 'wave01 level2'), lty = 'solid', lwd = 2, col = c(lcol_wave01, lcol_wave01_level2), inset = c(0.05, 0.15) )

0.2.1 Anomaly timeseries


par(mfrow= c(3,5), las = 1, mar = c(4,4,1,0))

linePlotMultiEns(years = sspyears, ens1 = npp_ens_anom_ssp585_S3,
                 ens2 = npp_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'NPP')

linePlotMultiEns(years = sspyears, ens1 = nbp_ens_anom_ssp585_S3,
                 ens2 = nbp_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'NBP')

linePlotMultiEns(years = sspyears, ens1 = cSoil_ens_anom_ssp585_S3,
                 ens2 = cSoil_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'cSoil')

linePlotMultiEns(years = sspyears, ens1 = cVeg_ens_anom_ssp585_S3,
                 ens2 = cVeg_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'cVeg')


linePlotMultiEns(years = sspyears, ens1 = rh_lnd_sum_ens_anom_ssp585_S3,
                 ens2 = rh_lnd_sum_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'RH')

linePlotMultiEns(years = sspyears, ens1 = fLuc_lnd_sum_ens_anom_ssp585_S3,
                 ens2 = fLuc_lnd_sum_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'fLuc')


linePlotMultiEns(years = sspyears, ens1 = lai_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = lai_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'LAI')

linePlotMultiEns(years = sspyears, ens1 = fHarvest_lnd_sum_ens_anom_ssp585_S3,
                 ens2 = fHarvest_lnd_sum_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = 'GtC', main = 'fHarvest')


linePlotMultiEns(years = sspyears, ens1 = treeFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = treeFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'treeFrac')

linePlotMultiEns(years = sspyears, ens1 = shrubFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = shrubFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'shrubFrac')

linePlotMultiEns(years = sspyears, ens1 = baresoilFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = baresoilFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'baresoilFrac')


linePlotMultiEns(years = sspyears, ens1 = c3PftFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = c3PftFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'c3PftFrac')

linePlotMultiEns(years = sspyears, ens1 = c4PftFrac_lnd_mean_ens_anom_ssp585_S3,
                 ens2 = c4PftFrac_lnd_mean_ens_anom_ssp585_S3[ix_kept, ],
                 col1 = lcol_wave01, col2 = lcol_wave01_level2,
                 ylab = '%', main = 'c4PftFrac')
reset()

legend('bottomright', legend = c('wave01', 'wave01 level2'), lty = 'solid', lwd = 2, col = c(lcol_wave01, lcol_wave01_level2), inset = c(0.05, 0.15) )

NA
NA

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgSlVMRVMxcDAgZW5zZW1ibGUgU1NQNTg1IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgdG9jX2RlcHRoOiAyCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwotLS0KClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIAoKVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiAKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz1GQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30KIyBMb2FkIGhlbHBlciBmdW5jdGlvbnMKCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcucGF0aCA9ICJmaWdzLyIsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5ncyA9IEZBTFNFKQoKCmBgYAoKYGBge3J9Cgpzb3VyY2UoIkpVTEVTLUVTLTFwMC1jb21tb24tcGFja2FnZXMuUiIpCnNvdXJjZSgiSlVMRVMtRVMtMXAwLWNvbW1vbi1mdW5jdGlvbnMuUiIpCmBgYAoKCmBgYHtyfQoKCm1ha2VUaW1lc2VyaWVzRW5zZW1ibGVTU1AgPC0gZnVuY3Rpb24oZW5zbG9jLCB2YXJpYWJsZSwgbnN0YXJ0LCBuZW5kLCBjbiA9IDE4NTA6MjEwMCl7CiAgCiAgeXNlYyA8LSAzMTUzNjAwMAogIAogIG5lbnMgPC0gKG5lbmQgLSBuc3RhcnQpICsgMQogICMgbmVucyBpcyBudW1iZXIgb2YgZW5zZW1ibGUgbWVtYmVycwogICMgbnRzIGxlbmd0aCBvZiB0aW1lc2VyaWVzCiAgIyBjbiBpcyBjb2xuYW1lcygpCiAgZGF0bWF0IDwtIG1hdHJpeChOQSwgbnJvdyA9IG5lbnMsIG5jb2wgPSBsZW5ndGgoY24pKQogIGNvbG5hbWVzKGRhdG1hdCkgPC0gY24KICAKICBlbnNsaXN0IDwtIHBhc3RlKCJQIiwgZm9ybWF0Qyhuc3RhcnQ6bmVuZCwgd2lkdGg9NCwgZmxhZz0iMCIpLCBzZXA9IiIpCiAgCiAgZm9yKGkgaW4gMTpuZW5zKXsKICAgIAogICAgZW5zbWVtYmVyIDwtIGVuc2xpc3RbaV0KICAgIAogICAgZm4gPC0gcGFzdGUwKGVuc2xvYywnSlVMRVMtRVMtMXAwXycsZW5zbWVtYmVyLCdfQW5udWFsX2dsb2JhbC5uYycpCiAgICAKICAgIHRyeShuYyA8LSBuY19vcGVuKHBhc3RlMChmbikpKQogICAgI3RyeShsb2NhbHRpbWUgPC0gbmN2YXJfZ2V0KG5jLCAndGltZScpKQogICAgCiAgICAjIFRoaXMgcGFydCBjb21wZW5zYXRlcyBmb3IgdGhlIGZhY3QgdGhhdCBzb21ldGltZXMgeWVhcnMgYXJlIG1pc3NpbmcKICAgICN0cnkobG9jYWx5ZWFyIDwtIGZsb29yKDIxMDAgKyAobG9jYWx0aW1lIC8geXNlYykpKQogICAgI3RyeShpeCA8LSB3aGljaChjbiVpbiVsb2NhbHllYXIpKQogICAgCiAgICB0cnkoZGF0IDwtIGV4dHJhY3RUaW1lc2VyaWVzKG5jLCB2YXJpYWJsZSkpCiAgICAKICAgIHRyeShkYXRtYXRbaSwgXSA8LSBkYXQpCiAgICBuY19jbG9zZShuYykKICB9CiAgZGF0bWF0Cn0KCmdldFN0YW5kYXJkTWVtYmVyU1NQIDwtIGZ1bmN0aW9uKGVuc2xvYywgdmFyaWFibGUsIG50cyA9IDI1MSwgY24gPSAxODUwOjIxMDApewogIAogIGRhdG1hdCA8LSBtYXRyaXgoTkEsIG5yb3cgPSAxLCBuY29sID0gbnRzKQogIGNvbG5hbWVzKGRhdG1hdCkgPC0gY24KICAKICBlbnNtZW1iZXIgPC0gJ1MzJwogICNmbiA8LSBwYXN0ZTAoZW5zbG9jLGVuc21lbWJlciwnL3N0YXRzLycsJ0pVTEVTLUVTLTFwMF8nLGVuc21lbWJlciwnX0FubnVhbF9nbG9iYWwubmMnKQogIGZuIDwtIHBhc3RlMChlbnNsb2MsJ0pVTEVTLUVTLTFwMF8nLGVuc21lbWJlciwnX0FubnVhbF9nbG9iYWwubmMnKQogIAogIHRyeShuYyA8LSBuY19vcGVuKHBhc3RlMChmbikpKQogIHRyeShkYXQgPC0gZXh0cmFjdFRpbWVzZXJpZXMobmMsIHZhcmlhYmxlKSkKICAKICBkYXRtYXRbMSwgXSA8LSBkYXQKICBuY19jbG9zZShuYykKICBkYXRtYXQKICAKfQoKCgpgYGAKCgoKYGBge3J9CgoKZW5zbG9jX3NzcDU4NV9TMyA8LSAnL2RhdGEvdXNlcnMvaGFkYXcvSlVMRVNfRVNfUFBFL3UtY2Y5MzIvJwplbnNsb2Nfc3NwNTg1X1JBRCA8LSAnL2RhdGEvdXNlcnMvaGFkYXcvSlVMRVNfRVNfUFBFL3UtY2s2NDcvJwoKeXNlYyA9IDYwKjYwKjI0KjM2NQpzc3B5ZWFycyA8LSAxODUwOjIxMDAKCgoKYGBgCgoKCmBgYHtyfQoKaWYgKGZpbGUuZXhpc3RzKCJlbnNlbWJsZV90aW1lc2VyaWVzX3NzcF8yMDIyLTA4LTA5LnJkYXRhIikpIHsKICBsb2FkKCJlbnNlbWJsZV90aW1lc2VyaWVzX3NzcF8yMDIyLTA4LTA5LnJkYXRhIikKfSBlbHNlIHsKICAKICAjIHByaW1hcnkgY2FyYm9uIGN5Y2xlIG91dHB1dHMKICBucHBfZW5zX3NzcDU4NV9TMyA8LSBtYWtlVGltZXNlcmllc0Vuc2VtYmxlU1NQKGVuc2xvYyA9IGVuc2xvY19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuc3RhcnQgPSA0OTksIG5lbmQgPSA5OTksIHZhcmlhYmxlID0gIm5wcF9ubGltX2xuZF9zdW0iLCBjbiA9IHNzcHllYXJzKSAvICgxZTEyL3lzZWMpCiAgCiAgbmJwX2Vuc19zc3A1ODVfUzMgPC0gbWFrZVRpbWVzZXJpZXNFbnNlbWJsZVNTUChlbnNsb2MgPSBlbnNsb2Nfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnN0YXJ0ID0gNDk5LCBuZW5kID0gOTk5LCB2YXJpYWJsZSA9ICJuYnBfbG5kX3N1bSIsIGNuID0gc3NweWVhcnMpIC8gKDFlMTIveXNlYykKICAKICBjU29pbF9lbnNfc3NwNTg1X1MzIDwtIG1ha2VUaW1lc2VyaWVzRW5zZW1ibGVTU1AoZW5zbG9jID0gZW5zbG9jX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5zdGFydCA9IDQ5OSwgbmVuZCA9IDk5OSwgdmFyaWFibGUgPSAiY1NvaWxfbG5kX3N1bSIsIGNuID0gc3NweWVhcnMpIC8gMWUxMgogIAogIGNWZWdfZW5zX3NzcDU4NV9TMyA8LSBtYWtlVGltZXNlcmllc0Vuc2VtYmxlU1NQKGVuc2xvYyA9IGVuc2xvY19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuc3RhcnQgPSA0OTksIG5lbmQgPSA5OTksIHZhcmlhYmxlID0gImNWZWdfbG5kX3N1bSIsIGNuID0gc3NweWVhcnMpIC8gMWUxMgogIAogIGxhaV9sbmRfbWVhbl9lbnNfc3NwNTg1X1MzIDwtIG1ha2VUaW1lc2VyaWVzRW5zZW1ibGVTU1AoZW5zbG9jID0gZW5zbG9jX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5zdGFydCA9IDQ5OSwgbmVuZCA9IDk5OSwgdmFyaWFibGUgPSAibGFpX2xuZF9tZWFuIiwgY24gPSBzc3B5ZWFycykKICAKICAjIGZsdXhlcwogIHJoX2xuZF9zdW1fZW5zX3NzcDU4NV9TMyA8LSBtYWtlVGltZXNlcmllc0Vuc2VtYmxlU1NQKGVuc2xvYyA9IGVuc2xvY19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuc3RhcnQgPSA0OTksIG5lbmQgPSA5OTksIHZhcmlhYmxlID0gInJoX2xuZF9zdW0iLCBjbiA9IHNzcHllYXJzKSAvICgxZTEyL3lzZWMpCiAgCiAgZkx1Y19sbmRfc3VtX2Vuc19zc3A1ODVfUzMgPC0gbWFrZVRpbWVzZXJpZXNFbnNlbWJsZVNTUChlbnNsb2MgPSBlbnNsb2Nfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnN0YXJ0ID0gNDk5LCBuZW5kID0gOTk5LCB2YXJpYWJsZSA9ICJmTHVjX2xuZF9zdW0iLCBjbiA9IHNzcHllYXJzKSAvICgxZTEyL3lzZWMpCiAKICBmSGFydmVzdF9sbmRfc3VtX2Vuc19zc3A1ODVfUzMgPC0gbWFrZVRpbWVzZXJpZXNFbnNlbWJsZVNTUChlbnNsb2MgPSBlbnNsb2Nfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnN0YXJ0ID0gNDk5LCBuZW5kID0gOTk5LCB2YXJpYWJsZSA9ICJmSGFydmVzdF9sbmRfc3VtIiwgY24gPSBzc3B5ZWFycykgLyAoMWUxMi95c2VjKQogIAogICMgZnJhY3Rpb25zCiAgdHJlZUZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMyA8LSBtYWtlVGltZXNlcmllc0Vuc2VtYmxlU1NQKGVuc2xvYyA9IGVuc2xvY19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuc3RhcnQgPSA0OTksIG5lbmQgPSA5OTksIHZhcmlhYmxlID0gInRyZWVGcmFjX2xuZF9tZWFuIiwgY24gPSBzc3B5ZWFycykKCiAgc2hydWJGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMgPC0gbWFrZVRpbWVzZXJpZXNFbnNlbWJsZVNTUChlbnNsb2MgPSBlbnNsb2Nfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnN0YXJ0ID0gNDk5LCBuZW5kID0gOTk5LCB2YXJpYWJsZSA9ICJzaHJ1YkZyYWNfbG5kX21lYW4iLCBjbiA9IHNzcHllYXJzKSAgCiAgCiAgYmFyZXNvaWxGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMgPC0gbWFrZVRpbWVzZXJpZXNFbnNlbWJsZVNTUChlbnNsb2MgPSBlbnNsb2Nfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnN0YXJ0ID0gNDk5LCBuZW5kID0gOTk5LCB2YXJpYWJsZSA9ICJiYXJlc29pbEZyYWNfbG5kX21lYW4iLCBjbiA9IHNzcHllYXJzKSAgCiAgCiAgYzNQZnRGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMgPC0gbWFrZVRpbWVzZXJpZXNFbnNlbWJsZVNTUChlbnNsb2MgPSBlbnNsb2Nfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnN0YXJ0ID0gNDk5LCBuZW5kID0gOTk5LCB2YXJpYWJsZSA9ICJjM1BmdEZyYWNfbG5kX21lYW4iLCBjbiA9IHNzcHllYXJzKSAKICAKICBjNFBmdEZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMyA8LSBtYWtlVGltZXNlcmllc0Vuc2VtYmxlU1NQKGVuc2xvYyA9IGVuc2xvY19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuc3RhcnQgPSA0OTksIG5lbmQgPSA5OTksIHZhcmlhYmxlID0gImM0UGZ0RnJhY19sbmRfbWVhbiIsIGNuID0gc3NweWVhcnMpICAgCiAgCiAgc2F2ZShucHBfZW5zX3NzcDU4NV9TMywgbmJwX2Vuc19zc3A1ODVfUzMsIGNTb2lsX2Vuc19zc3A1ODVfUzMsIGNWZWdfZW5zX3NzcDU4NV9TMywgbGFpX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsIHJoX2xuZF9zdW1fZW5zX3NzcDU4NV9TMywgZkx1Y19sbmRfc3VtX2Vuc19zc3A1ODVfUzMsIGZIYXJ2ZXN0X2xuZF9zdW1fZW5zX3NzcDU4NV9TMywKICAgICAgIHRyZWVGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsIHNocnViRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLCBiYXJlc29pbEZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMyxjM1BmdEZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMywgYzRQZnRGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsCiAgICAgICBmaWxlID0gImVuc2VtYmxlX3RpbWVzZXJpZXNfc3NwXzIwMjItMDgtMDkucmRhdGEiICkKICAKfQoKCgoKYGBgCgoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CgojIG5wcF9zdGFuX3NzcDU4NV9TMzwtIGdldFN0YW5kYXJkTWVtYmVyKGVuc2xvYyA9IGVuc2xvY193YXZlMDAsIHZhcmlhYmxlID0gIm5wcF9ubGltX2xuZF9zdW0iKSAvICgxZTEyL3lzZWMpCiMgbmJwX3N0YW5fc3NwNTg1X1MzIDwtIGdldFN0YW5kYXJkTWVtYmVyKGVuc2xvYyA9IGVuc2xvY193YXZlMDAsIHZhcmlhYmxlID0gIm5icF9sbmRfc3VtIikgLyAoMWUxMi95c2VjKQojIGNTb2lsX3N0YW5fc3NwNTg1X1MzIDwtIGdldFN0YW5kYXJkTWVtYmVyKGVuc2xvYyA9IGVuc2xvY193YXZlMDAsIHZhcmlhYmxlID0gImNTb2lsX2xuZF9zdW0iKSAvIDFlMTIKIyBjVmVnX3N0YW5fc3NwNTg1X1MzIDwtIGdldFN0YW5kYXJkTWVtYmVyKGVuc2xvYyA9IGVuc2xvY193YXZlMDAsIHZhcmlhYmxlID0gImNWZWdfbG5kX3N1bSIpIC8gMWUxMgojIGxhaV9sbmRfbWVhbl9zdGFuX3NzcDU4NV9TMyA8LSBnZXRTdGFuZGFyZE1lbWJlcihlbnNsb2MgPSBlbnNsb2Nfd2F2ZTAwLCB2YXJpYWJsZSA9ICJsYWlfbG5kX21lYW4iKQojIAojIAojICMgZmx1eGVzCiMgcmhfbG5kX3N1bV9zdGFuX3NzcDU4NV9TMyA8LSBnZXRTdGFuZGFyZE1lbWJlcihlbnNsb2MgPSBlbnNsb2Nfd2F2ZTAwLCB2YXJpYWJsZSA9ICJyaF9sbmRfc3VtIikgLyAoMWUxMi95c2VjKQojIGZMdWNfbG5kX3N1bV9zdGFuX3NzcDU4NV9TMyA8LSBnZXRTdGFuZGFyZE1lbWJlcihlbnNsb2MgPSBlbnNsb2Nfd2F2ZTAwLCB2YXJpYWJsZSA9ICJmTHVjX2xuZF9zdW0iKSAvICgxZTEyL3lzZWMpCiMgZkhhcnZlc3RfbG5kX3N1bV9zdGFuX3NzcDU4NV9TMyA8LSBnZXRTdGFuZGFyZE1lbWJlcihlbnNsb2MgPSBlbnNsb2Nfd2F2ZTAwLCB2YXJpYWJsZSA9ICJmSGFydmVzdF9sbmRfc3VtIikgLyAoMWUxMi95c2VjKQojIAojIAojICMgZnJhY3Rpb25zCiMgdHJlZUZyYWNfbG5kX21lYW5fc3Rhbl9zc3A1ODVfUzMgPC0gZ2V0U3RhbmRhcmRNZW1iZXIoZW5zbG9jID0gZW5zbG9jX3dhdmUwMCwgdmFyaWFibGUgPSAidHJlZUZyYWNfbG5kX21lYW4iKQojIHNocnViRnJhY19sbmRfbWVhbl9zdGFuX3NzcDU4NV9TMyA8LSBnZXRTdGFuZGFyZE1lbWJlcihlbnNsb2MgPSBlbnNsb2Nfd2F2ZTAwLCB2YXJpYWJsZSA9ICJzaHJ1YkZyYWNfbG5kX21lYW4iKQojIGJhcmVzb2lsRnJhY19sbmRfbWVhbl9zdGFuX3NzcDU4NV9TMyA8LSBnZXRTdGFuZGFyZE1lbWJlcihlbnNsb2MgPSBlbnNsb2Nfd2F2ZTAwLCB2YXJpYWJsZSA9ICJiYXJlc29pbEZyYWNfbG5kX21lYW4iKQojIGMzUGZ0RnJhY19sbmRfbWVhbl9zdGFuX3NzcDU4NV9TMyA8LSBnZXRTdGFuZGFyZE1lbWJlcihlbnNsb2MgPSBlbnNsb2Nfd2F2ZTAwLCB2YXJpYWJsZSA9ICJjM1BmdEZyYWNfbG5kX21lYW4iKQojIGM0UGZ0RnJhY19sbmRfbWVhbl9zdGFuX3NzcDU4NV9TMyA8LSBnZXRTdGFuZGFyZE1lbWJlcihlbnNsb2MgPSBlbnNsb2Nfd2F2ZTAwLCB2YXJpYWJsZSA9ICJjNFBmdEZyYWNfbG5kX21lYW4iKQoKCgpgYGAKCgpgYGB7cn0KIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIyBBbm9tYWxpemUgZW5zZW1ibGUKIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKbnBwX2Vuc19hbm9tX3NzcDU4NV9TMyA8LSBhbm9tYWxpemVUU21hdHJpeChucHBfZW5zX3NzcDU4NV9TMywgMToyMCkKbmJwX2Vuc19hbm9tX3NzcDU4NV9TMyA8LSBhbm9tYWxpemVUU21hdHJpeChuYnBfZW5zX3NzcDU4NV9TMywgMToyMCkKY1NvaWxfZW5zX2Fub21fc3NwNTg1X1MzIDwtIGFub21hbGl6ZVRTbWF0cml4KGNTb2lsX2Vuc19zc3A1ODVfUzMsIDE6MjApCmNWZWdfZW5zX2Fub21fc3NwNTg1X1MzIDwtIGFub21hbGl6ZVRTbWF0cml4KGNWZWdfZW5zX3NzcDU4NV9TMywgMToyMCkKCnJoX2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzIDwtIGFub21hbGl6ZVRTbWF0cml4KHJoX2xuZF9zdW1fZW5zX3NzcDU4NV9TMywgMToyMCkKZkx1Y19sbmRfc3VtX2Vuc19hbm9tX3NzcDU4NV9TMyA8LSBhbm9tYWxpemVUU21hdHJpeChmTHVjX2xuZF9zdW1fZW5zX3NzcDU4NV9TMywgMToyMCkKbGFpX2xuZF9tZWFuX2Vuc19hbm9tX3NzcDU4NV9TMyA8LSBhbm9tYWxpemVUU21hdHJpeChsYWlfbG5kX21lYW5fZW5zX3NzcDU4NV9TMywgMToyMCkgCgpmSGFydmVzdF9sbmRfc3VtX2Vuc19hbm9tX3NzcDU4NV9TMyA8LSBhbm9tYWxpemVUU21hdHJpeChmSGFydmVzdF9sbmRfc3VtX2Vuc19zc3A1ODVfUzMsIDE6MjApCnRyZWVGcmFjX2xuZF9tZWFuX2Vuc19hbm9tX3NzcDU4NV9TMyA8LSBhbm9tYWxpemVUU21hdHJpeCh0cmVlRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLCAxOjIwKQpzaHJ1YkZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzIDwtIGFub21hbGl6ZVRTbWF0cml4KHNocnViRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLCAxOjIwKQpiYXJlc29pbEZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzIDwtIGFub21hbGl6ZVRTbWF0cml4KGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLCAxOjIwKQpjM1BmdEZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzIDwtIGFub21hbGl6ZVRTbWF0cml4KGMzUGZ0RnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLCAxOjIwKQpjNFBmdEZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzIDwtIGFub21hbGl6ZVRTbWF0cml4KGM0UGZ0RnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLCAxOjIwKQoKI3RvdGFsX2xhbmRfY2FyYm9uX2Fub20gPC0gYW5vbWFsaXplVFNtYXRyaXgodG90YWxfbGFuZF9jYXJib25fZW5zLCAxOjIwKQoKCmBgYAoKYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gMTJ9Cgp0cmFuc3B2YWwgPC0gMzAKbGluZWNvbCA9ICdibGFjaycKCnBhcihtZnJvdz0gYygzLDUpLCBsYXMgPSAxLCBtYXIgPSBjKDQsNCwxLDEpKQoKbWF0cGxvdChzc3B5ZWFycywgdChucHBfZW5zX3NzcDU4NV9TMyksCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICdOUFAnLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJykKCm1hdHBsb3Qoc3NweWVhcnMsdChuYnBfZW5zX3NzcDU4NV9TMyksCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICdOQlAnLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJykKCm1hdHBsb3Qoc3NweWVhcnMsdChjU29pbF9lbnNfc3NwNTg1X1MzKSwgCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICdjU29pbCcsIHhsYWIgPSAnJywgeWxhYiA9ICdHdEMnKQogCm1hdHBsb3Qoc3NweWVhcnMsdChjVmVnX2Vuc19zc3A1ODVfUzMpLAogICAgICAgIHR5cGUgPSAnbCcsIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLCAKICAgICAgICBtYWluID0gJ2NWZWcnLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJyApCgptYXRwbG90KHNzcHllYXJzLHQocmhfbG5kX3N1bV9lbnNfc3NwNTg1X1MzICksCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICdSSCcsIHhsYWIgPSAnJywgeWxhYiA9ICdHdEMnKQoKbWF0cGxvdChzc3B5ZWFycyx0KGZMdWNfbG5kX3N1bV9lbnNfc3NwNTg1X1MzKSwKICAgICAgICB0eXBlID0gJ2wnLCBsdHkgPSAnc29saWQnLCBjb2wgPSBtYWtlVHJhbnNwYXJlbnQobGluZWNvbCwgdHJhbnNwdmFsKSwKICAgICAgICBtYWluID0gJ2ZMdWMnLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJykKCm1hdHBsb3Qoc3NweWVhcnMsdChsYWlfbG5kX21lYW5fZW5zX3NzcDU4NV9TMyksCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICdMQUknLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJykKCm1hdHBsb3Qoc3NweWVhcnMsdChmSGFydmVzdF9sbmRfc3VtX2Vuc19zc3A1ODVfUzMpLCAKICAgICAgICB0eXBlID0gJ2wnLCBsdHkgPSAnc29saWQnLCBjb2wgPSBtYWtlVHJhbnNwYXJlbnQobGluZWNvbCwgdHJhbnNwdmFsKSwKICAgICAgICBtYWluID0gJ2ZIYXJ2ZXN0JywgeGxhYiA9ICcnLCB5bGFiID0gJ0d0QycpCgptYXRwbG90KHNzcHllYXJzLHQodHJlZUZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMyksCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICd0cmVlRnJhYycsIHhsYWIgPSAnJywgeWxhYiA9ICclJykKCm1hdHBsb3Qoc3NweWVhcnMsdChzaHJ1YkZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMyksIAogICAgICAgIHR5cGUgPSAnbCcsIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLAogICAgICAgIG1haW4gPSAnc2hydWJGcmFjJywgeGxhYiA9ICcnLCB5bGFiID0gJyUnKQoKbWF0cGxvdChzc3B5ZWFycyx0KGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzKSwKICAgICAgICB0eXBlID0gJ2wnLCBsdHkgPSAnc29saWQnLCBjb2wgPSBtYWtlVHJhbnNwYXJlbnQobGluZWNvbCwgdHJhbnNwdmFsKSwKICAgICAgICBtYWluID0gJ2JhcmVzb2lsRnJhYycsIHhsYWIgPSAnJywgeWxhYiA9ICclJykKCm1hdHBsb3Qoc3NweWVhcnMsdChjM1BmdEZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMyksIHR5cGUgPSAnbCcsIAogICAgICAgIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLAogICAgICAgIG1haW4gPSAnYzNQZnRGcmFjJywgeGxhYiA9ICcnLCB5bGFiID0gJyUnKQoKbWF0cGxvdChzc3B5ZWFycyx0KGM0UGZ0RnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzKSwKICAgICAgICB0eXBlID0gJ2wnLCBsdHkgPSAnc29saWQnLCBjb2wgPSBtYWtlVHJhbnNwYXJlbnQobGluZWNvbCwgdHJhbnNwdmFsKSwKICAgICAgICBtYWluID0gJ2M0UGZ0RnJhYycsIHhsYWIgPSAnJyx5bGFiID0gJyUnKQoKCmBgYAoKCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDEyfQoKdHJhbnNwdmFsIDwtIDMwCmxpbmVjb2wgPSAnYmxhY2snCgpwYXIobWZyb3c9IGMoMyw1KSwgbGFzID0gMSwgbWFyID0gYyg0LDQsMSwxKSkKCm1hdHBsb3Qoc3NweWVhcnMsIHQobnBwX2Vuc19hbm9tX3NzcDU4NV9TMyksCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICdOUFAnLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJykKCm1hdHBsb3Qoc3NweWVhcnMsdChuYnBfZW5zX2Fub21fc3NwNTg1X1MzKSwKICAgICAgICB0eXBlID0gJ2wnLCBsdHkgPSAnc29saWQnLCBjb2wgPSBtYWtlVHJhbnNwYXJlbnQobGluZWNvbCwgdHJhbnNwdmFsKSwKICAgICAgICBtYWluID0gJ05CUCcsIHhsYWIgPSAnJywgeWxhYiA9ICdHdEMnKQoKbWF0cGxvdChzc3B5ZWFycyx0KGNTb2lsX2Vuc19hbm9tX3NzcDU4NV9TMyksIAogICAgICAgIHR5cGUgPSAnbCcsIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLAogICAgICAgIG1haW4gPSAnY1NvaWwnLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJykKIAptYXRwbG90KHNzcHllYXJzLHQoY1ZlZ19lbnNfYW5vbV9zc3A1ODVfUzMpLAogICAgICAgIHR5cGUgPSAnbCcsIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLCAKICAgICAgICBtYWluID0gJ2NWZWcnLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJyApCgptYXRwbG90KHNzcHllYXJzLHQocmhfbG5kX3N1bV9lbnNfYW5vbV9zc3A1ODVfUzMgKSwKICAgICAgICB0eXBlID0gJ2wnLCBsdHkgPSAnc29saWQnLCBjb2wgPSBtYWtlVHJhbnNwYXJlbnQobGluZWNvbCwgdHJhbnNwdmFsKSwKICAgICAgICBtYWluID0gJ1JIJywgeGxhYiA9ICcnLCB5bGFiID0gJ0d0QycpCgptYXRwbG90KHNzcHllYXJzLHQoZkx1Y19sbmRfc3VtX2Vuc19hbm9tX3NzcDU4NV9TMyksCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICdmTHVjJywgeGxhYiA9ICcnLCB5bGFiID0gJ0d0QycpCgptYXRwbG90KHNzcHllYXJzLHQobGFpX2xuZF9tZWFuX2Vuc19hbm9tX3NzcDU4NV9TMyksCiAgICAgICAgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJywgY29sID0gbWFrZVRyYW5zcGFyZW50KGxpbmVjb2wsIHRyYW5zcHZhbCksCiAgICAgICAgbWFpbiA9ICdMQUknLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJykKCm1hdHBsb3Qoc3NweWVhcnMsdChmSGFydmVzdF9sbmRfc3VtX2Vuc19hbm9tX3NzcDU4NV9TMyksIAogICAgICAgIHR5cGUgPSAnbCcsIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLAogICAgICAgIG1haW4gPSAnZkhhcnZlc3QnLCB4bGFiID0gJycsIHlsYWIgPSAnR3RDJykKCm1hdHBsb3Qoc3NweWVhcnMsdCh0cmVlRnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzMpLAogICAgICAgIHR5cGUgPSAnbCcsIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLAogICAgICAgIG1haW4gPSAndHJlZUZyYWMnLCB4bGFiID0gJycsIHlsYWIgPSAnJScpCgptYXRwbG90KHNzcHllYXJzLHQoc2hydWJGcmFjX2xuZF9tZWFuX2Vuc19hbm9tX3NzcDU4NV9TMyksIAogICAgICAgIHR5cGUgPSAnbCcsIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLAogICAgICAgIG1haW4gPSAnc2hydWJGcmFjJywgeGxhYiA9ICcnLCB5bGFiID0gJyUnKQoKbWF0cGxvdChzc3B5ZWFycyx0KGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzMpLAogICAgICAgIHR5cGUgPSAnbCcsIGx0eSA9ICdzb2xpZCcsIGNvbCA9IG1ha2VUcmFuc3BhcmVudChsaW5lY29sLCB0cmFuc3B2YWwpLAogICAgICAgIG1haW4gPSAnYmFyZXNvaWxGcmFjJywgeGxhYiA9ICcnLCB5bGFiID0gJyUnKQoKbWF0cGxvdChzc3B5ZWFycyx0KGMzUGZ0RnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzMpLCB0eXBlID0gJ2wnLCAKICAgICAgICBsdHkgPSAnc29saWQnLCBjb2wgPSBtYWtlVHJhbnNwYXJlbnQobGluZWNvbCwgdHJhbnNwdmFsKSwKICAgICAgICBtYWluID0gJ2MzUGZ0RnJhYycsIHhsYWIgPSAnJywgeWxhYiA9ICclJykKCm1hdHBsb3Qoc3NweWVhcnMsdChjNFBmdEZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzKSwKICAgICAgICB0eXBlID0gJ2wnLCBsdHkgPSAnc29saWQnLCBjb2wgPSBtYWtlVHJhbnNwYXJlbnQobGluZWNvbCwgdHJhbnNwdmFsKSwKICAgICAgICBtYWluID0gJ2M0UGZ0RnJhYycsIHhsYWIgPSAnJyx5bGFiID0gJyUnKQoKCmBgYAoKCiMjIFdoaWNoIGVuc2VtYmxlIG1lbWJlcnMgbWF0Y2ggY29uc3RyYWludHM/CgpTdGFydCB3aXRoIExldmVsIDIgKEFuZHkncyBjb25zdHJhaW50cyBpbiBOUFAsIE5CUCwgY1NvaWwgYW5kIGNWZWcpCgpgYGB7cn0KCml4X212IDwtIHdoaWNoKHNzcHllYXJzICVpbiUgMTk5NjoyMDE1KQoKeXZlY19jb25zdHJhaW50cyA8LSBjKCducHBfZW5zX3NzcDU4NV9TMycsICduYnBfZW5zX3NzcDU4NV9TMycsICdjU29pbF9lbnNfc3NwNTg1X1MzJywgJ2NWZWdfZW5zX3NzcDU4NV9TMycpCgojIE1hdHJpeCBvZiBjb25zdHJhaW50IG91dHB1dCBtb2Rlcm4gdmFsdWVzICgxOTk2IC0gMjAxNSkKWV9jb25zdF9zc3A1ODVfbXYgPC0gbWF0cml4KGRhdGEgPSBOQSwgbnJvdyA9IG5yb3cobnBwX2Vuc19zc3A1ODVfUzMpLCBuY29sID0gbGVuZ3RoKHl2ZWNfY29uc3RyYWludHNfdmVjICkpCmNvbG5hbWVzKFlfY29uc3Rfc3NwNTg1X212KSA8LSB5dmVjX2NvbnN0cmFpbnRzCgpmb3IoaSBpbiAxOmxlbmd0aCh5dmVjX2NvbnN0cmFpbnRzKSl7CiAgCiAgWV90cnVuYyA8LSBnZXQoeXZlY19jb25zdHJhaW50c1tpXSlbLCBpeF9tdl0KICBZX3RydW5jX21lYW4gPC0gYXBwbHkoWV90cnVuYywgMSwgbWVhbiwgbmEucm0gPSBUUlVFKQogIFlfY29uc3Rfc3NwNTg1X212WyxpXSA8LSBZX3RydW5jX21lYW4KfQoKYGBgCgoKYGBge3J9CgpjcmVhdGVDb25zdHJhaW50U3RyaW5nIDwtIGZ1bmN0aW9uKHl2ZWMsIG1pbnMsIG1heGVzKXsKICAjIFRoaXMgZnVuY3Rpb24gY29uc3RydWN0cyBhIGxvZ2ljYWwgZXhwcmVzc2lvbiBhcyBhIHN0cmluZyB0byBiZSBldmFsdWF0ZWQKICBvdXQgPC0gJ3doaWNoKCcKICAKICBmb3IoaSBpbiAxOmxlbmd0aCh5dmVjKSl7CiAgICAKICAgIGlmKGk8bGVuZ3RoKHl2ZWMpKXsKICAgICAgCiAgICBzdWJjb25zdCA8LSBwYXN0ZTAoJ1lfdW5pZicsJ1ssJywgJyInLHl2ZWNbaV0sJyInLCddJywgJz4nLCBtaW5zW2ldLCAnJicsICdZX3VuaWYnLCdbLCcsICciJyx5dmVjW2ldLCAnIicsJ10nICwgJzwnLCBtYXhlc1tpXSwgJyYnKQogICAgfQogICAgCiAgICBlbHNlewogICAgIHN1YmNvbnN0IDwtICBwYXN0ZTAoJ1lfdW5pZicsJ1ssJywgJyInLHl2ZWNbaV0sJyInLCddJywgJz4nLCBtaW5zW2ldLCAnJicsICdZX3VuaWYnLCdbLCcsICciJyx5dmVjW2ldLCAnIicsJ10nICwgJzwnLCBtYXhlc1tpXSkKICAgIH0KICAgb3V0IDwtICBwYXN0ZTAob3V0LCBzdWJjb25zdCkKICB9CiAgCiAgb3V0IDwtIHBhc3RlMChvdXQsICcpJykKfQoKCkFXX21pbnMgPC0gYygzNSwgMCwgNzUwLCAzMDApCkFXX21heGVzIDwtIGMoODAsIDEwMDAwLCAzMDAwLCA4MDApCgpZX3VuaWYgPC0gWV9jb25zdF9zc3A1ODVfbXYKaXhfa2VwdCA8LSBldmFsKHBhcnNlKHRleHQgPSBjcmVhdGVDb25zdHJhaW50U3RyaW5nKHl2ZWM9eXZlY19jb25zdHJhaW50cywgbWlucyA9IEFXX21pbnMsIG1heGVzID0gQVdfbWF4ZXMpKSkKCgoKI2V2YWwocGFyc2UodGV4dCA9IHBhc3RlMCgpKSkKCmlucHV0Q29uc3RyYWludFNpemUgPC0gZnVuY3Rpb24oWV91bmlmLCB5dmVjLCBtaW5zLCBtYXhlcyl7CiAgIyBDYWxjdWxhdGUgdGhlIGluZGljZXMgb2YgWV91bmlmIHRoYXQgYXJlIHdpdGhpbiB0aGUgYm91bmRzIHNldCBieSBtaW5zIGFuZCBtYXhlcwogIAogIAogIGl4X2tlcHQgPC0gZXZhbChwYXJzZSh0ZXh0ID0gY3JlYXRlQ29uc3RyYWludFN0cmluZyh5dmVjPXl2ZWMsIG1pbnMgPSBtaW5zLCBtYXhlcyA9IG1heGVzKSkpCiAgCiAgcHJvcF9rZXB0IDwtIGxlbmd0aChpeF9rZXB0KSAvIG5yb3coWV91bmlmKQogIAogIHJldHVybihsaXN0KGl4X2tlcHQgPSBpeF9rZXB0LCBwcm9wX2tlcHQgPSBwcm9wX2tlcHQpKQogIAp9CiAgCmBgYAoKIyMjIFRpbWVzZXJpZXMgb2YgYWJzb2x1dGUgdmFsZXMKCmBgYHtyLCBmaWcud2lkdGggPSAxMCwgZmlnLmhlaWdodCA9IDEyfQoKbGNvbF93YXZlMDEgPC0gbWFrZVRyYW5zcGFyZW50KCdmaXJlYnJpY2snLCAgODApCmxjb2xfd2F2ZTAxX2xldmVsMiA8LSBtYWtlVHJhbnNwYXJlbnQoJ2dvbGQnLCAgODApCnN0YW5jb2wgPSAnYmxhY2snCgpsaW5lUGxvdE11bHRpRW5zIDwtIGZ1bmN0aW9uKHllYXJzLCBlbnMxLCBlbnMyLCBjb2wxLCBjb2wyLCB5bGFiLCBtYWluLCB5bGltID0gTlVMTCl7CiAgIyBQbG90IHdhdmUwMCBhbmQgd2F2ZTAxIHRpbWVzZXJpZXMgb24gdG9wIG9mIG9uZSBhbm90aGVyCiAgCiAgbnQgPC0gbGVuZ3RoKHllYXJzKSAKICBpZihpcy5udWxsKHlsaW0pKXsKICAgIAogICN5bGltID0gcmFuZ2UoYyhlbnMxWywxXSwgZW5zMVssbnRdLCBlbnMyWywxXSwgZW5zMlsgLG50XSkpCiAgeWxpbSA9IHJhbmdlKGMoZW5zMSxlbnMyKSkKICB9CiAgCiAgZWxzZSB5bGltIDwtIHlsaW0KICAKICBtYXRwbG90KHllYXJzLCB0KGVuczEpLCB0eXBlID0gJ2wnLCBsdHkgPSAnc29saWQnLHlsaW0gPSB5bGltLCBjb2wgPSBjb2wxLAogICAgICAgIHlsYWIgPSB5bGFiLCBtYWluID0gbWFpbiwgeGxhYiA9ICcnLAogICAgICAgIGJ0eSA9ICduJywgbHdkID0gMS41KQogIG1hdGxpbmVzKHllYXJzLCB0KGVuczIpLCBjb2wgPSBjb2wyLCBsdHkgPSAnc29saWQnLCBsd2QgPSAxLjUpCn0KCgpwYXIobWZyb3c9IGMoMyw1KSwgbGFzID0gMSwgbWFyID0gYyg0LDQsMSwwKSkKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IG5wcF9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBucHBfZW5zX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJ0d0QycsIG1haW4gPSAnTlBQJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IG5icF9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBuYnBfZW5zX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJ0d0QycsIG1haW4gPSAnTkJQJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGNTb2lsX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGNTb2lsX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ2NTb2lsJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGNWZWdfZW5zX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICBlbnMyID0gY1ZlZ19lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdjVmVnJykKCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSByaF9sbmRfc3VtX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IHJoX2xuZF9zdW1fZW5zX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJ0d0QycsIG1haW4gPSAnUkgnKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gZkx1Y19sbmRfc3VtX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGZMdWNfbG5kX3N1bV9lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdmTHVjJykKCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBsYWlfbG5kX21lYW5fZW5zX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICBlbnMyID0gbGFpX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ0xBSScpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBmSGFydmVzdF9sbmRfc3VtX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGZIYXJ2ZXN0X2xuZF9zdW1fZW5zX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJ0d0QycsIG1haW4gPSAnZkhhcnZlc3QnKQoKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IHRyZWVGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IHRyZWVGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICd0cmVlRnJhYycpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBzaHJ1YkZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICBlbnMyID0gc2hydWJGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICdzaHJ1YkZyYWMnKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gYmFyZXNvaWxGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnJScsIG1haW4gPSAnYmFyZXNvaWxGcmFjJykKCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBjM1BmdEZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICBlbnMyID0gYzNQZnRGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICdjM1BmdEZyYWMnKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gYzRQZnRGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGM0UGZ0RnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnJScsIG1haW4gPSAnYzRQZnRGcmFjJykKcmVzZXQoKQoKbGVnZW5kKCdib3R0b21yaWdodCcsIGxlZ2VuZCA9IGMoJ3dhdmUwMScsICd3YXZlMDEgbGV2ZWwyJyksIGx0eSA9ICdzb2xpZCcsIGx3ZCA9IDIsIGNvbCA9IGMobGNvbF93YXZlMDEsIGxjb2xfd2F2ZTAxX2xldmVsMiksIGluc2V0ID0gYygwLjA1LCAwLjE1KSApCgpgYGAKCiMjIyBBbm9tYWx5IHRpbWVzZXJpZXMKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gMTJ9CgpwYXIobWZyb3c9IGMoMyw1KSwgbGFzID0gMSwgbWFyID0gYyg0LDQsMSwwKSkKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IG5wcF9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IG5wcF9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ05QUCcpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBuYnBfZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBuYnBfZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdOQlAnKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gY1NvaWxfZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBjU29pbF9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ2NTb2lsJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGNWZWdfZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBjVmVnX2Vuc19hbm9tX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJ0d0QycsIG1haW4gPSAnY1ZlZycpCgoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gcmhfbG5kX3N1bV9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IHJoX2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdSSCcpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBmTHVjX2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBmTHVjX2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdmTHVjJykKCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBsYWlfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBsYWlfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdMQUknKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gZkhhcnZlc3RfbG5kX3N1bV9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGZIYXJ2ZXN0X2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdmSGFydmVzdCcpCgoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gdHJlZUZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSB0cmVlRnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICd0cmVlRnJhYycpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBzaHJ1YkZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBzaHJ1YkZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnJScsIG1haW4gPSAnc2hydWJGcmFjJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICdiYXJlc29pbEZyYWMnKQoKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGMzUGZ0RnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGMzUGZ0RnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICdjM1BmdEZyYWMnKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gYzRQZnRGcmFjX2xuZF9tZWFuX2Vuc19hbm9tX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICBlbnMyID0gYzRQZnRGcmFjX2xuZF9tZWFuX2Vuc19hbm9tX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJyUnLCBtYWluID0gJ2M0UGZ0RnJhYycpCnJlc2V0KCkKCmxlZ2VuZCgnYm90dG9tcmlnaHQnLCBsZWdlbmQgPSBjKCd3YXZlMDEnLCAnd2F2ZTAxIGxldmVsMicpLCBsdHkgPSAnc29saWQnLCBsd2QgPSAyLCBjb2wgPSBjKGxjb2xfd2F2ZTAxLCBsY29sX3dhdmUwMV9sZXZlbDIpLCBpbnNldCA9IGMoMC4wNSwgMC4xNSkgKQoKCmBgYAoKCiMjIEluY2x1ZGUgVHJlZSBmcmFjdGlvbiBkYXRhCgpgYGB7cn0KCmxvYWQoJ3RyZWVmcmFjL2dsb2JhbF9mcmFjX2NjaS5SRGF0YScpCgpmcmFjX2NjaSA8LSBjKGdsb2JhbF9mcmFjX2NjaVsxXSArIGdsb2JhbF9mcmFjX2NjaVsyXSwgZ2xvYmFsX2ZyYWNfY2NpWzNdLCBnbG9iYWxfZnJhY19jY2lbNF0sIGdsb2JhbF9mcmFjX2NjaVs1XSwgZ2xvYmFsX2ZyYWNfY2NpWzhdICkKI2ZyYWNfbXYgPC0gYyhzdGFuZGFyZF9tb2Rlcm5fdmFsdWVbJ3RyZWVGcmFjX2xuZF9tZWFuJ10sIHN0YW5kYXJkX21vZGVybl92YWx1ZVsnYzNQZnRGcmFjX2xuZF9tZWFuJ10sICNzdGFuZGFyZF9tb2Rlcm5fdmFsdWVbJ2M0UGZ0RnJhY19sbmRfbWVhbiddLCBzdGFuZGFyZF9tb2Rlcm5fdmFsdWVbJ3NocnViRnJhY19sbmRfbWVhbiddLCBzdGFuZGFyZF9tb2Rlcm5fdmFsdWVbJ2JhcmVzb2lsRnJhY19sbmRfbWVhbiddICApCgoKZnJhY2xhYiA9IGMoJ1RyZWVzJywgJ0MzIGdyYXNzZXMnLCAnQzQgZ3Jhc3NlcycsICdTaHJ1YnMnLCAnQmFyZSBzb2lsJykKCgojIEhhbGYgYW5kIGRvdWJsZSB0aGUgTEMgQ0NJIGRhdGEgdG8gZ2V0IGJvdW5kcyBmb3IgY29uc3RyYWluaW5nIEpVTEVTIEVTLTEuMApmcmFjX2NjaV9tYXggPC0gZnJhY19jY2kgKyAoMC41KmZyYWNfY2NpKQpmcmFjX2NjaV9taW4gPC0gZnJhY19jY2kgLSAoMC41KmZyYWNfY2NpKQoKYGBgCgoKYGBge3J9CgppeF9tdiA8LSB3aGljaChzc3B5ZWFycyAlaW4lIDE5OTY6MjAxNSkKCnl2ZWNfY29uc3RyYWludHMgPC0gYygnbnBwX2Vuc19zc3A1ODVfUzMnLCAnbmJwX2Vuc19zc3A1ODVfUzMnLCAnY1NvaWxfZW5zX3NzcDU4NV9TMycsICdjVmVnX2Vuc19zc3A1ODVfUzMnLCdiYXJlc29pbEZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TMycpCgojIE1hdHJpeCBvZiBjb25zdHJhaW50IG91dHB1dCBtb2Rlcm4gdmFsdWVzICgxOTk2IC0gMjAxNSkKWV9jb25zdF9zc3A1ODVfbXYgPC0gbWF0cml4KGRhdGEgPSBOQSwgbnJvdyA9IG5yb3cobnBwX2Vuc19zc3A1ODVfUzMpLCBuY29sID0gbGVuZ3RoKHl2ZWNfY29uc3RyYWludHMpKQpjb2xuYW1lcyhZX2NvbnN0X3NzcDU4NV9tdikgPC0geXZlY19jb25zdHJhaW50cwoKZm9yKGkgaW4gMTpsZW5ndGgoeXZlY19jb25zdHJhaW50cykpewogIAogIFlfdHJ1bmMgPC0gZ2V0KHl2ZWNfY29uc3RyYWludHNbaV0pWywgaXhfbXZdCiAgWV90cnVuY19tZWFuIDwtIGFwcGx5KFlfdHJ1bmMsIDEsIG1lYW4sIG5hLnJtID0gVFJVRSkKICBZX2NvbnN0X3NzcDU4NV9tdlssaV0gPC0gWV90cnVuY19tZWFuCn0KCmBgYAoKYGBge3J9CmNvbnN0X21pbnMgPC0gYygzNSwgMCwgNzUwLCAzMDAsIGZyYWNfY2NpX21pblsnYmFyZSBzb2lsJ10qMTAwKQpjb25zdF9tYXhlcyA8LSBjKDgwLCAxMDAwMCwgMzAwMCwgODAwLCBmcmFjX2NjaV9tYXhbJ2JhcmUgc29pbCddKjEwMCkKCllfdW5pZiA8LSBZX2NvbnN0X3NzcDU4NV9tdgppeF9rZXB0IDwtIGV2YWwocGFyc2UodGV4dCA9IGNyZWF0ZUNvbnN0cmFpbnRTdHJpbmcoeXZlYz15dmVjX2NvbnN0cmFpbnRzLCBtaW5zID0gY29uc3RfbWlucywgbWF4ZXMgPSBjb25zdF9tYXhlcykpKQoKYGBgCgoKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gMTJ9CgpsY29sX3dhdmUwMSA8LSBtYWtlVHJhbnNwYXJlbnQoJ2ZpcmVicmljaycsICAxMjApCmxjb2xfd2F2ZTAxX2xldmVsMiA8LSBtYWtlVHJhbnNwYXJlbnQoJ2dvbGQnLCAgMTIwKQpzdGFuY29sID0gJ2JsYWNrJwoKbGluZVBsb3RNdWx0aUVucyA8LSBmdW5jdGlvbih5ZWFycywgZW5zMSwgZW5zMiwgY29sMSwgY29sMiwgeWxhYiwgbWFpbiwgeWxpbSA9IE5VTEwpewogICMgUGxvdCB3YXZlMDAgYW5kIHdhdmUwMSB0aW1lc2VyaWVzIG9uIHRvcCBvZiBvbmUgYW5vdGhlcgogIAogIG50IDwtIGxlbmd0aCh5ZWFycykgCiAgaWYoaXMubnVsbCh5bGltKSl7CiAgICAKICAjeWxpbSA9IHJhbmdlKGMoZW5zMVssMV0sIGVuczFbLG50XSwgZW5zMlssMV0sIGVuczJbICxudF0pKQogIHlsaW0gPSByYW5nZShjKGVuczEsZW5zMikpCiAgfQogIAogIGVsc2UgeWxpbSA8LSB5bGltCiAgCiAgbWF0cGxvdCh5ZWFycywgdChlbnMxKSwgdHlwZSA9ICdsJywgbHR5ID0gJ3NvbGlkJyx5bGltID0geWxpbSwgY29sID0gY29sMSwKICAgICAgICB5bGFiID0geWxhYiwgbWFpbiA9IG1haW4sIHhsYWIgPSAnJywKICAgICAgICBidHkgPSAnbicsIGx3ZCA9IDEuNSkKICBtYXRsaW5lcyh5ZWFycywgdChlbnMyKSwgY29sID0gY29sMiwgbHR5ID0gJ3NvbGlkJywgbHdkID0gMS41KQp9CgoKcGFyKG1mcm93PSBjKDMsNSksIGxhcyA9IDEsIG1hciA9IGMoNCw0LDEsMCkpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBucHBfZW5zX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICBlbnMyID0gbnBwX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ05QUCcpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBuYnBfZW5zX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICBlbnMyID0gbmJwX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ05CUCcpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBjU29pbF9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBjU29pbF9lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdjU29pbCcpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBjVmVnX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGNWZWdfZW5zX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJ0d0QycsIG1haW4gPSAnY1ZlZycpCgoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gcmhfbG5kX3N1bV9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSByaF9sbmRfc3VtX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ1JIJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGZMdWNfbG5kX3N1bV9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBmTHVjX2xuZF9zdW1fZW5zX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJ0d0QycsIG1haW4gPSAnZkx1YycpCgoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gbGFpX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGxhaV9sbmRfbWVhbl9lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdMQUknKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gZkhhcnZlc3RfbG5kX3N1bV9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBmSGFydmVzdF9sbmRfc3VtX2Vuc19zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ2ZIYXJ2ZXN0JykKCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSB0cmVlRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSB0cmVlRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnJScsIG1haW4gPSAndHJlZUZyYWMnKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gc2hydWJGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IHNocnViRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnJScsIG1haW4gPSAnc2hydWJGcmFjJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBiYXJlc29pbEZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJyUnLCBtYWluID0gJ2JhcmVzb2lsRnJhYycpCgoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gYzNQZnRGcmFjX2xuZF9tZWFuX2Vuc19zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGMzUGZ0RnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnJScsIG1haW4gPSAnYzNQZnRGcmFjJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGM0UGZ0RnJhY19sbmRfbWVhbl9lbnNfc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBjNFBmdEZyYWNfbG5kX21lYW5fZW5zX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJyUnLCBtYWluID0gJ2M0UGZ0RnJhYycpCnJlc2V0KCkKCmxlZ2VuZCgnYm90dG9tcmlnaHQnLCBsZWdlbmQgPSBjKCd3YXZlMDEnLCAnd2F2ZTAxIGxldmVsMicpLCBsdHkgPSAnc29saWQnLCBsd2QgPSAyLCBjb2wgPSBjKGxjb2xfd2F2ZTAxLCBsY29sX3dhdmUwMV9sZXZlbDIpLCBpbnNldCA9IGMoMC4wNSwgMC4xNSkgKQoKYGBgCiMjIyBBbm9tYWx5IHRpbWVzZXJpZXMKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gMTJ9CgpwYXIobWZyb3c9IGMoMyw1KSwgbGFzID0gMSwgbWFyID0gYyg0LDQsMSwwKSkKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IG5wcF9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IG5wcF9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ05QUCcpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBuYnBfZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBuYnBfZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdOQlAnKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gY1NvaWxfZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBjU29pbF9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICdHdEMnLCBtYWluID0gJ2NTb2lsJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGNWZWdfZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBjVmVnX2Vuc19hbm9tX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJ0d0QycsIG1haW4gPSAnY1ZlZycpCgoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gcmhfbG5kX3N1bV9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IHJoX2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdSSCcpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBmTHVjX2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBmTHVjX2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdmTHVjJykKCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBsYWlfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBsYWlfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdMQUknKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gZkhhcnZlc3RfbG5kX3N1bV9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGZIYXJ2ZXN0X2xuZF9zdW1fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnR3RDJywgbWFpbiA9ICdmSGFydmVzdCcpCgoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gdHJlZUZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSB0cmVlRnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICd0cmVlRnJhYycpCgpsaW5lUGxvdE11bHRpRW5zKHllYXJzID0gc3NweWVhcnMsIGVuczEgPSBzaHJ1YkZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzLAogICAgICAgICAgICAgICAgIGVuczIgPSBzaHJ1YkZyYWNfbG5kX21lYW5fZW5zX2Fub21fc3NwNTg1X1MzW2l4X2tlcHQsIF0sCiAgICAgICAgICAgICAgICAgY29sMSA9IGxjb2xfd2F2ZTAxLCBjb2wyID0gbGNvbF93YXZlMDFfbGV2ZWwyLAogICAgICAgICAgICAgICAgIHlsYWIgPSAnJScsIG1haW4gPSAnc2hydWJGcmFjJykKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGJhcmVzb2lsRnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICdiYXJlc29pbEZyYWMnKQoKCmxpbmVQbG90TXVsdGlFbnMoeWVhcnMgPSBzc3B5ZWFycywgZW5zMSA9IGMzUGZ0RnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzMsCiAgICAgICAgICAgICAgICAgZW5zMiA9IGMzUGZ0RnJhY19sbmRfbWVhbl9lbnNfYW5vbV9zc3A1ODVfUzNbaXhfa2VwdCwgXSwKICAgICAgICAgICAgICAgICBjb2wxID0gbGNvbF93YXZlMDEsIGNvbDIgPSBsY29sX3dhdmUwMV9sZXZlbDIsCiAgICAgICAgICAgICAgICAgeWxhYiA9ICclJywgbWFpbiA9ICdjM1BmdEZyYWMnKQoKbGluZVBsb3RNdWx0aUVucyh5ZWFycyA9IHNzcHllYXJzLCBlbnMxID0gYzRQZnRGcmFjX2xuZF9tZWFuX2Vuc19hbm9tX3NzcDU4NV9TMywKICAgICAgICAgICAgICAgICBlbnMyID0gYzRQZnRGcmFjX2xuZF9tZWFuX2Vuc19hbm9tX3NzcDU4NV9TM1tpeF9rZXB0LCBdLAogICAgICAgICAgICAgICAgIGNvbDEgPSBsY29sX3dhdmUwMSwgY29sMiA9IGxjb2xfd2F2ZTAxX2xldmVsMiwKICAgICAgICAgICAgICAgICB5bGFiID0gJyUnLCBtYWluID0gJ2M0UGZ0RnJhYycpCnJlc2V0KCkKCmxlZ2VuZCgnYm90dG9tcmlnaHQnLCBsZWdlbmQgPSBjKCd3YXZlMDEnLCAnd2F2ZTAxIGxldmVsMicpLCBsdHkgPSAnc29saWQnLCBsd2QgPSAyLCBjb2wgPSBjKGxjb2xfd2F2ZTAxLCBsY29sX3dhdmUwMV9sZXZlbDIpLCBpbnNldCA9IGMoMC4wNSwgMC4xNSkgKQoKCmBgYAoKCgpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4KClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4K